adds or subtracts 16-bit values to produce a 16-bit result, permitting overflow.
PBASIC allows you to add or subtract any two variables--bits, bytes, words, or a mixture--to get a 16-bit result. If a sum is larger than 16 bits, the highest-order bits are lost. If a difference is negative, it is a two's complement number.
The PIC's native instruction set includes 8-bit addition with a carry bit that is set when a sum exceeds 0FFh. This routine for 16-bit addition adds the LSBs first. If a carry occurs, it increments the MSB of the sum, then adds the MSBs.
While it is possible to code a separate subtraction routine in much the same way, it turns out to be easier to convert the number to be subtracted into a negative number instead. This is known as taking the two's complement of a number, and it just a matter of inverting the bits and adding 1. Two's complement numbers occur naturally in the kind of integer math that the PIC performs. Try subtracting 50 from 30 using the native PIC instruction sub. You'll get 236. Of course the answer should be -20. OK, take the two's complement of 20 using the Parallax instruction neg. You'll get 236.
So adding the two's complement of a number is the same as subtracting that
number. This technique is used in other instructions throughout this book
(e.g., Pause and Sleep) when it is more convenient to increment a negative
number up to zero than to decrement a positive number down to zero. The reason
is that the instructions inc and dec affect the zero bit, but not the carry
bit. When a number is incremented, a carry occurs at the same time the number
rolls over to zero. So the zero bit can be used to dete ct a carry when
incrementing. This doesn't work when decrementing. The number hits zero one
decrement before a carry would occur.
To see these routines in operation, either run the program with the PSIM simulator, or connect the circuit below to an erasable PIC or PIC emulator, such as the Parallax downloader. Assemble and run ADD_SUB.SRC. When you apply power to the PIC, the LEDs will light up in the binary pattern of the answer to the math problem C836h - 2575h, which is A2C1h. That works out to the following binary pattern on the LEDs:
1010 0010 1100 0001
Try adding and subtracting various combinations of n1 and n2 to see different results.
; ; *************************************************************************** ; *** Bubble Software Parallax to PIC Source Converter. Copyright 1999. *** ; *** http://www.bubblesoftonline.com email: sales@picnpoke.com *** ; *************************************************************************** ; ; ADD/SUBTRACT n1, n2 ; Add two 16-bit numbers to produce a 16-bit result, permitting overflow. ; Add the two's complement of one 16-bit number to another 16-bit number ; to perform subtraction, permitting underflow. ; Addition: n1 = n1 + n2 ; Subtraction: n1 = n1 - n2 ; Device data and reset vector P = pic16c55 #include <16c55.inc> ; processor assembler definitions _CONFIG _xt_osc & _wdt_off & _protect_off reset start org 8 n1H Res d'1' ; MSB of n1. n1L Res d'1' ; LSB of n1. n2H Res d'1' ; MSB of n2. n2L Res d'1' ; LSB of n2. org 0 start MOVLW d'0' ; Outputs for LEDs to TRIS 6h MOVLW d'0' ; display 16-bit result. TRIS 7h MOVLW 0x00C8 ; Problem: C836h-2575h MOVWF n1H MOVLW 0x36 MOVWF n1L MOVLW 0x25 MOVWF n2H MOVLW 0x75 MOVWF n2L CALL Sub16 ; n1 = n1 - n2 MOVF n1L,w ; Show result in binary on MOVWF 6h MOVF n1H,w ; LEDs connected to ports. MOVWF 7h GOTO $ ; Endless loop Sub16 COMF n2H ; Take two's complement COMF n2L ; of n2. If zero, n2L INCF n2L BTFSC status,z ; overflowed, so carry INCF n2H ; into n2H. Add16 MOVF n2L,w ; Add the LSBs. If carry, ADDWF n1L BTFSC status,c ; increment MSB of sum. INCF n1H MOVF n2H,w ; Add the MSBs ADDWF n1H RETLW 0h end
; ADD/SUBTRACT n1, n2 ; Add two 16-bit numbers to produce a 16-bit result, permitting overflow. ; Add the two's complement of one 16-bit number to another 16-bit number ; to perform subtraction, permitting underflow. ; Addition: n1 = n1 + n2 ; Subtraction: n1 = n1 - n2 org 8 n1H ds 1 ; MSB of n1. n1L ds 1 ; LSB of n1. n2H ds 1 ; MSB of n2. n2L ds 1 ; LSB of n2. ; Device data and reset vector device pic16c55,xt_osc,wdt_off,protect_off reset start org 0 start mov !rb,#0 ; Outputs for LEDs to mov !rc,#0 ; display 16-bit result. mov n1H,#0C8h ; Problem: C836h-2575h mov n1L,#36h mov n2H,#25h mov n2L,#75h call Sub16 ; n1 = n1 - n2 mov rb,n1L ; Show result in binary on mov rc,n1H ; LEDs connected to ports. jmp $ ; Endless loop Sub16 NOT n2H ; Take two's complement NEG n2L ; of n2. If zero, n2L snz ; overflowed, so carry inc n2H ; into n2H. Add16 ADD n1L,n2L ; Add the LSBs. If carry, snc ; increment MSB of sum. inc n1H ADD n1H,n2H ; Add the MSBs ret
See also: